package com.hopes.bizz.poll.statistic.service.support;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.hopes.bizz.common.core.util.CollectionUtils;
import com.hopes.bizz.poll.analy.dto.AnalyzeTrendDTO;
import com.hopes.bizz.poll.analy.vo.CompareItemVO;
import com.hopes.bizz.poll.analy.vo.CompareTrendVO;
import com.hopes.bizz.poll.common.constant.AnalyzeTrendConstant;
import com.hopes.bizz.poll.factor.entity.PollFactorInfoEntity;
import com.hopes.bizz.poll.monitor.entity.PollMonitorFactorEntity;
import com.hopes.bizz.poll.monitor.entity.PollMonitorSiteEntity;
import com.hopes.bizz.poll.monitor.service.PollMonitorFactorService;
import com.hopes.bizz.poll.om.entity.BaseOmDataEntity;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author yumr
 * @ProjectName bizz
 * @Description 统计分析支撑类
 * @time 2023/5/30 11:16
 */
public abstract class StatisticAnalyzeSupport {

    @Resource
    private PollMonitorFactorService pollMonitorFactorService;

    /**
     * 处理时间
     *
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @param mapper    函数，格式化时间
     * @param calendar  类型 如: Calendar.DAY_OF_YEAR, Calendar.HOUR_OF_DAY 等
     * @param step      步长
     * @return 结果
     */
    protected List<String> handlerDateTime(Date beginTime, Date endTime, Function<Date, String> mapper, Integer calendar, Integer step) {
        final List<String> list = new ArrayList<>();
        final Calendar instance = Calendar.getInstance();
        instance.setTime(beginTime);
        while (instance.getTimeInMillis() <= endTime.getTime()) {
            final String apply = mapper.apply(instance.getTime());
            list.add(apply);
            instance.add(calendar, step);
        }
        return list;
    }

    /**
     * 处理站点、因子数据
     *
     * @param analyzeTrendDTO   查询对象
     * @param dateTimeList      时间数据
     * @param monitorFactorList 监测因子
     * @return 返回值
     */
    protected JSONArray handlerDataDisplayType(String tittle, Function<Date, String> mapper, AnalyzeTrendDTO analyzeTrendDTO,
                                               List<PollMonitorSiteEntity> monitorSiteList, List<String> dateTimeList,
                                               List<PollFactorInfoEntity> monitorFactorList, List<BaseOmDataEntity> pollDayEntityList) {
        final JSONArray result = new JSONArray();
        final Integer dataDisplayType = analyzeTrendDTO.getDataDisplayType();
        if (dataDisplayType.equals(AnalyzeTrendConstant.DISPLAY_TYPE_SINGLE_SITE)) {
            // 单站点多因子
            for (PollMonitorSiteEntity entity : monitorSiteList) {
                final JSONObject siteInfo = new JSONObject();
                siteInfo.put("id", entity.getId());
                siteInfo.put("timeArray", dateTimeList);
                siteInfo.put("displayType", dataDisplayType);
                siteInfo.put("title", entity.getName() + tittle);

                final JSONArray jsonArray = new JSONArray();
                for (PollFactorInfoEntity factorInfoEntity : monitorFactorList) {
                    final JSONObject jsonObject = buildInitData(factorInfoEntity.getId(), factorInfoEntity.getName(), dateTimeList);
                    // 更新数据
                    updateData(entity.getId(), factorInfoEntity.getCode(), analyzeTrendDTO.getDataAnalyzeType(), jsonObject, mapper, pollDayEntityList, dateTimeList);
                    jsonArray.add(jsonObject);
                }
                siteInfo.put("factorArray", jsonArray);  // 所有因子数据
                result.add(siteInfo);
            }

        } else if (dataDisplayType.equals(AnalyzeTrendConstant.DISPLAY_TYPE_SINGLE_FACTOR)) {
            // 多站单因子
            for (PollFactorInfoEntity entity : monitorFactorList) {
                final JSONObject factorInfo = new JSONObject();
                factorInfo.put("id", entity.getId());
                factorInfo.put("timeArray", dateTimeList);
                factorInfo.put("title", entity.getName() + tittle);
                factorInfo.put("displayType", dataDisplayType);

                final JSONArray jsonArray = new JSONArray();
                for (PollMonitorSiteEntity monitorSiteEntity : monitorSiteList) {
                    final JSONObject jsonObject = buildInitData(monitorSiteEntity.getId(), monitorSiteEntity.getName(), dateTimeList);
                    // 更新数据
                    updateData(monitorSiteEntity.getId(), entity.getCode(), analyzeTrendDTO.getDataAnalyzeType(), jsonObject, mapper, pollDayEntityList, dateTimeList);
                    jsonArray.add(jsonObject);
                }
                factorInfo.put("siteArray", jsonArray);
                result.add(factorInfo);
            }
        }
        return result;
    }


    private void updateData(Long monitorSiteId, String factorCode, Integer dataAnalyzeType, JSONObject factorData, Function<Date, String> mapper, List<BaseOmDataEntity> pollDayEntityList, List<String> dateTimeList) {
        // 过滤数据
        final List<BaseOmDataEntity> collect = pollDayEntityList.parallelStream().filter(e -> null != e.getMonitorSiteId()).filter(e -> e.getMonitorSiteId().equals(monitorSiteId)).collect(Collectors.toList());
        for (BaseOmDataEntity omDataEntity : collect) {
            // 时间数据
            final String apply = mapper.apply(omDataEntity.getDataTime());
            final int index = dateTimeList.indexOf(apply);
            if (index != -1) {
                final List<String> data = JSONObject.parseArray(JSON.toJSONString(factorData.get("data")), String.class);
                final JSONObject omData = JSON.parseObject(JSON.toJSONString(omDataEntity.getDataJson()));
                if (omData.containsKey(factorCode)) {
                    final JSONObject object = omData.getJSONObject(factorCode);
                    // 取排放量
                    if (dataAnalyzeType.equals(AnalyzeTrendConstant.ANALYZE_DATA_TYPE_COU)) {
                        data.set(index, MapUtil.getStr(object, "cou"));
                    } else if (dataAnalyzeType.equals(AnalyzeTrendConstant.ANALYZE_DATA_TYPE_ZS)) {
                        data.set(index, MapUtil.getStr(object, "zsval"));
                    } else if (dataAnalyzeType.equals(AnalyzeTrendConstant.ANALYZE_DATA_TYPE_VAL)) {
                        data.set(index, MapUtil.getStr(object, "val"));
                    }
                }
                factorData.put("data", data);
            }
        }
    }

    private JSONObject buildInitData(Long id, String name, List<String> dateTimeList) {
        final JSONObject res = new JSONObject();
        res.put("id", id);
        res.put("name", name);
        res.put("data", dateTimeList.stream().map(item -> "0").collect(Collectors.toList()));
        return res;
    }


    protected List<CompareTrendVO> buildCompareTrendList(Long monitorSiteId, Integer dataAnalyzeType, List<String> dateTimeList,
                                                         List<PollFactorInfoEntity> factorInfoList, Function<Date, String> mapper,
                                                         List<BaseOmDataEntity> currentOmData, List<BaseOmDataEntity> compareOmData) {
        final List<CompareTrendVO> list = new ArrayList<>();
        for (PollFactorInfoEntity factorInfo : factorInfoList) {
            final CompareTrendVO compareTrendVO = new CompareTrendVO();
            compareTrendVO.setId(factorInfo.getId());
            compareTrendVO.setTitle(factorInfo.getName() + "同比趋势");
            compareTrendVO.setTimeArray(dateTimeList);

            final PollMonitorFactorEntity monitorFactorEntity = pollMonitorFactorService.getMonitorFactorBySiteAndFactorId(monitorSiteId, factorInfo.getId());
            compareTrendVO.setFactorUnit(Optional.ofNullable(monitorFactorEntity).map(PollMonitorFactorEntity::getUnit).orElse(null));
            compareTrendVO.setMaxAlarm(Optional.ofNullable(monitorFactorEntity).map(PollMonitorFactorEntity::getMaxAlarm).orElse(new BigDecimal(0)));
            final CompareItemVO currentItemVo = buildCompareItemVo("当前", dataAnalyzeType, dateTimeList, mapper, currentOmData, factorInfo);
            final CompareItemVO compareItemVo = buildCompareItemVo("同比", dataAnalyzeType, dateTimeList, mapper, compareOmData, factorInfo);
            compareTrendVO.setDataArray(Arrays.asList(currentItemVo, compareItemVo));
            list.add(compareTrendVO);
        }
        return list;
    }

    private CompareItemVO buildCompareItemVo(String tittle, Integer dataAnalyzeType, List<String> dateTimeList, Function<Date, String> mapper, List<BaseOmDataEntity> omDataList, PollFactorInfoEntity factorInfo) {
        final CompareItemVO itemVO = new CompareItemVO();
        itemVO.setName(tittle);
        itemVO.setData(dateTimeList.stream().map(item -> "0").collect(Collectors.toList()));
        if (CollectionUtils.isEmpty(omDataList)) {
            return itemVO;
        }
        for (BaseOmDataEntity omDataEntity : omDataList) {
            final String apply = mapper.apply(omDataEntity.getDataTime());
            final int index = dateTimeList.indexOf(apply);
            if (index == -1) {
                continue;
            }
            final JSONObject omData = JSON.parseObject(JSON.toJSONString(omDataEntity.getDataJson()));
            if (!omData.containsKey(factorInfo.getCode())) {
                continue;
            }
            final JSONObject object = omData.getJSONObject(factorInfo.getCode());
            // 取排放量
            if (dataAnalyzeType.equals(AnalyzeTrendConstant.ANALYZE_DATA_TYPE_COU)) {
                itemVO.getData().set(index, MapUtil.getStr(object, "cou"));
            } else if (dataAnalyzeType.equals(AnalyzeTrendConstant.ANALYZE_DATA_TYPE_ZS)) {
                itemVO.getData().set(index, MapUtil.getStr(object, "zsval"));
            } else if (dataAnalyzeType.equals(AnalyzeTrendConstant.ANALYZE_DATA_TYPE_VAL)) {
                itemVO.getData().set(index, MapUtil.getStr(object, "val"));
            }
        }
        return itemVO;
    }

    public JSONObject handlerDataGIS(List<String> dateTimeList, List<PollFactorInfoEntity> factorInfoList, List<? extends BaseOmDataEntity> list, Function<Date, String> mapper) {
        JSONObject siteInfo = new JSONObject();
        siteInfo.put("timeArray", dateTimeList);
        JSONArray jsonArray = new JSONArray();
        for (PollFactorInfoEntity factorInfoEntity : factorInfoList) {
            JSONObject jsonObject = this.buildInitData(factorInfoEntity.getId(), factorInfoEntity.getName(), dateTimeList);
            for (BaseOmDataEntity omDataEntity : list) {
                String dateTime = mapper.apply(omDataEntity.getDataTime());
                int index = dateTimeList.indexOf(dateTime);
                if (index != -1) {
                    List<BigDecimal> data = JSONObject.parseArray(JSON.toJSONString(jsonObject.get("data")), BigDecimal.class);
                    JSONObject omData = JSON.parseObject(JSON.toJSONString(omDataEntity.getDataJson()));
                    if (omData.containsKey(factorInfoEntity.getCode())) {
                        JSONObject object = omData.getJSONObject(factorInfoEntity.getCode());

                        data.set(index, data.get(index).add(object.getBigDecimal("val")));
                    }
                    jsonObject.put("data", data);
                    jsonObject.put("unit", factorInfoEntity.getStatisticUnit());
                }
            }
            jsonArray.add(jsonObject);
        }

        siteInfo.put("factorArray", jsonArray);
        return siteInfo;
    }

}
